﻿using Conmmon;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Conmmon
{

    //public class ConmmodityInfo {
    //    public int ID { get; set; }
    //    public string  ConmmdittName { get; set; }
    //    public bool  MyProperty { get; set; }
    //}
    public class HelloProducer
    {
        public static List<string> _conmmodityInfos = new  List<string >();

        static HelloProducer()
        {
            for (int i = 0; i < 1000; i++)
            {
                _conmmodityInfos.Add($"商品{i}");
            }
        }

        /// <summary>
        /// 发布订阅的模式（使用交换机）
        /// </summary>
        public static void Producer_ExChanges()
        {

            // 获取TCP 长连接
            using (var connection = RabbitMQHelper.GetConnection())
            {
                // 创建通信通道， 相当于TCP中虚拟链接
                using (var channel = connection.CreateModel())
                {
                    string message = $"伞兵1号，已经准备就绪";
                    var body = Encoding.UTF8.GetBytes(message);
                    /**
                     * exchange:交换机，在进行发布订阅的时候才能使用到
                     * 路由KEY
                     * 额外的设置属性
                     * 最后一个参数是要传递的消息字节数组
                     *
                     * **/
                    channel.BasicPublish("amq.fanout", "", null, body);

                    Console.WriteLine($"消息：{message}已发送");
                }

            }
        }


        /// <summary>
        /// 发布订阅模式
        /// </summary>
        public static void Consumer_Issue_Take()
        {
            var dis = new Dictionary<string, object>();
            dis.Add("x-dead-letter-exchange", "Test.dead");
            dis.Add("x-dead-letter-routing-key", "testDead");
            var message = RabbitMQHelper.Consunmer("lianyu", "", "", dis);

            message.OnCallback = (str) =>
            {
                Console.WriteLine($"消费者2接收消息：{str.Content}");
                return true;
            };
            Console.ReadLine();
        }




        /// <summary>
        /// 生产者 点对点（一对多）
        /// </summary>
        public static void Producer()
        {
            for (int i = 0; i < 10; i++)
            {
                string messages = $"伞兵{i}号，已经准备就绪";
                //string messages = $"伞兵i号，已经准备就绪";
                /**
                 * exchange:交换机，在进行发布订阅的时候才能使用到
                 * 路由KEY
                 * 额外的设置属性
                 * 最后一个参数是要传递的消息字节数组
                 *  amq.fanout
                 * **/

                var dis = new Dictionary<string, object>();
                dis.Add("x-dead-letter-exchange", "Test.dead");
                dis.Add("x-dead-letter-routing-key", "testDead");
                RabbitMQHelper.Producer(messages, "lianyu", "", "", dis, 1000 * 20);

                Console.WriteLine($"消息：{messages}已发送");
            }

            return;

            // 获取TCP 长连接
            using (var connection = RabbitMQHelper.GetConnection())
            {
                // 创建通信通道， 相当于TCP中虚拟链接
                using (var channel = connection.CreateModel())
                {

                    /***
                     * 
                     * 创建队列，声明并创建一个队列，如果队列已存在，这使用这个队列
                     * 第一个参数：队列ID
                     * 第二个参数：是否持久化，false对应不持久化数据,MQ停止之后数据就会丢失
                     * 第三个参数：是否队列私有化，false则代表所有的消费者都可以访问，true代表只有第一次拥有它的消费者才能一直使用
                     * 第四个参数: 是否自动删除，false代表链接停掉之后不自动删除这个队列
                     * 其他额外参数为null
                     * 
                     * **/

                    channel.QueueDeclare("HelloWorld", true, false, false, null);

                    for (int i = 0; i < 1000; i++)
                    {
                        string message = $"伞兵{i}号，已经准备就绪";
                        var body = Encoding.UTF8.GetBytes(message);
                        /**
                         * exchange:交换机，在进行发布订阅的时候才能使用到
                         * 路由KEY
                         * 额外的设置属性
                         * 最后一个参数是要传递的消息字节数组
                         *
                         * **/

                        channel.BasicPublish("", "HelloWorld", null, body);

                        Console.WriteLine($"消息：{message}已发送");
                    }

                }
            }

        }



        /// <summary>
        /// 生产者 点对点（一对一）
        /// </summary>
        //public static void Producer()
        //{
        //    // 获取TCP 长连接
        //    using (var connection = RabbitMQHelper.GetConnection())
        //    {
        //        // 创建通信通道， 相当于TCP中虚拟链接
        //        using (var channel = connection.CreateModel())
        //        {

        //            /***
        //             * 
        //             * 创建队列，声明并创建一个队列，如果队列已存在，这使用这个队列
        //             * 第一个参数：队列ID
        //             * 第二个参数：是否持久化，false对应不持久化数据,MQ停止之后数据就会丢失
        //             * 第三个参数：是否队列私有化，false则代表所有的消费者都可以访问，true代表只有第一次拥有它的消费者才能一直使用
        //             * 第四个参数: 是否自动删除，false代表链接停掉之后不自动删除这个队列
        //             * 其他额外参数为null
        //             * 
        //             * **/

        //            channel.QueueDeclare("HelloWorld", true, false, false, null);
        //            string message = "hello CodeMan";
        //            var body = Encoding.UTF8.GetBytes(message);

        //            /**
        //             * exchange:交换机，在进行发布订阅的时候才能使用到
        //             * 路由KEY
        //             * 额外的设置属性
        //             * 最后一个参数是要传递的消息字节数组
        //             *
        //             * **/

        //            channel.BasicPublish("", "HelloWorld", null, body);

        //            Console.WriteLine($"producer消息：{message}已发送");
        //        }
        //    }

        //}






        /// <summary>
        /// 消费者
        /// </summary>
        public async static void Consunmer()
        {

            // 获取TCP 长连接
            using (var connection = RabbitMQHelper.GetConnection())
            {
                // 创建通信通道， 相当于TCP中虚拟链接
                using (var channel = connection.CreateModel())
                {

                    /***
                     * 
                     * 创建队列，声明并创建一个队列，如果队列已存在，这使用这个队列
                     * 第一个参数：队列ID
                     * 第二个参数：是否持久化，false对应不持久化数据,MQ停止之后数据就会丢失
                     * 第三个参数：是否队列私有化，false则代表所有的消费者都可以访问，true代表只有第一次拥有它的消费者才能一直使用
                     * 第四个参数: 是否自动删除，false代表链接停掉之后不自动删除这个队列
                     * 其他额外参数为null
                     * 
                     * **/

                    channel.QueueDeclare("HelloWorld", true, false, false, null);


                    //创建事件
                    EventingBasicConsumer comsumers = new EventingBasicConsumer(channel);

                    //触发事件
                    await Task.Run(() =>
                     {
                         comsumers.Received += (model, ea) =>
                         {
                             var body = ea.Body.ToArray();
                             var message = Encoding.UTF8.GetString(body);

                             //false知识确认签收当前的消息，设置为true的时候则代表签收该消费者所有未签收的消息
                             channel.BasicAck(ea.DeliveryTag, false);
                             Console.WriteLine($"Consumer01接收消息：{message}");
                         };

                         /***
                         * 从MQ服务器中获取数据
                         * 创建一个消息消费者
                         * 第一个参数：队列名
                         * 第二个参数：是否自动确认收到消息，false代表手动确认消息，这个是MQ推荐的做法
                         * 第三个参数：要传入IBasicConsumer接口
                         *
                         * **/
                         channel.BasicConsume("HelloWorld", false, comsumers);
                         Console.WriteLine("Press [Enter] to exit");
                         Console.Read();
                     });



                }
            }

        }



        //队列名称
        //****==================订单延时队列=======================*****//
        //订单延时队列
        private static string DELAY_QUEUE_NAME = "delay-queue-orderOverTime";
        //订单延时消费队列
        private static string CONSUME_QUEUE_NAME = "consume-queue-orderOverTime";
        //订单延时队列死信交换的交换器名称
        private static string EXCHANGENAME = "exchange-orderOverTime";
        //订单延时队列死信的交换器路由key
        private static string ROUTINGKEY = "routingKey-orderOverTime";

        public static void Testdelad()
        {

            var connection = RabbitMQHelper.GetConnection();

            var delayChannel = connection.CreateModel();//延时队列连接通道

            var consumerChannel = connection.CreateModel();//消费队列连接通道

            consumerChannel.ExchangeDeclare(EXCHANGENAME, "direct");//创建交换器

            Dictionary<string, object> arg = new Dictionary<string, object>();
            //配置死信交换器
            arg.Add("x-dead-letter-exchange", EXCHANGENAME); //交换器名称
                                                             //死信交换路由key （交换器可以将死信交换到很多个其他的消费队列，可以用不同的路由key 来将死信路由到不同的消费队列去）
            arg.Add("x-dead-letter-routing-key", ROUTINGKEY);
            delayChannel.QueueDeclare(DELAY_QUEUE_NAME, true, false, false, arg);

            /**创建消费队列*/
            consumerChannel.QueueDeclare(CONSUME_QUEUE_NAME, true, false, false, null);
            //参数1:绑定的队列名  参数2:绑定至哪个交换器  参数3:绑定路由key
            consumerChannel.QueueBind(CONSUME_QUEUE_NAME, EXCHANGENAME, ROUTINGKEY);
            //最多接受条数 0为无限制，每次消费消息数(根据实际场景设置)，true=作用于整channel,false=作用于具体的消费者
            consumerChannel.BasicQos(0, 10, false);
            int i = 20;
            while (i > 0)
            {
                var body = Encoding.UTF8.GetBytes("你牛逼奥！" + i);
                var properties = delayChannel.CreateBasicProperties();
                //properties.DeliveryMode = 2;
                //properties.Expiration = "15000";
                delayChannel.BasicPublish("", DELAY_QUEUE_NAME, properties, body);
                i--;
            }

        }


        public static void Testdeald1()
        {

            var connection = RabbitMQHelper.GetConnection();

            var channel = connection.CreateModel();
            Dictionary<string, object> arg = new Dictionary<string, object>();
            //配置死信交换器
            arg.Add("x-dead-letter-exchange", EXCHANGENAME); //交换器名称
                                                             //死信交换路由key （交换器可以将死信交换到很多个其他的消费队列，可以用不同的路由key 来将死信路由到不同的消费队列去）
            arg.Add("x-dead-letter-routing-key", ROUTINGKEY);
            channel.QueueDeclare("delay-queue-orderOverTime", true, false, false, arg);

            var consumer = new EventingBasicConsumer(channel);
            channel.BasicConsume("delay-queue-orderOverTime", false, consumer);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body;
                var message = Encoding.UTF8.GetString(body.ToArray());
                Console.WriteLine("已拒绝： {0}", message);
                //Console.WriteLine("已接收： {0}", message);
                //channel.BasicAck(ea.DeliveryTag, false);

                channel.BasicNack(ea.DeliveryTag, false, false);
            };
            consumer.HandleBasicConsumeOk("ok");
            Console.ReadLine();
        }

    }



}
